Skip to content

docs: join the Python build to the libtmux.org shared shell - #755

Open
tony wants to merge 11 commits into
masterfrom
docs-site
Open

docs: join the Python build to the libtmux.org shared shell#755
tony wants to merge 11 commits into
masterfrom
docs-site

Conversation

@tony

@tony tony commented Sep 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Add docs/_static/libtmux-org.css, the design-token adapter mapping the site's shared --lt-* tokens onto Furo's own --color-* contract. tokens.css restyles nothing by itself; without this translation table a page carries the variables unused in the cascade and still paints Furo's stock blue.
  • Load the shell's header, footer, and version switcher through /_shell/shell.js, so the Python build wears the same chrome as the other ports.
  • Redirect Sphinx's built-in search page to the shell's Pagefind search, which covers every port. Furo's search UI needs a client-side index this build does not emit at that path.
  • Gate both on LIBTMUX_DOCS_STANDALONE, so the tree docs.yml publishes to the bucket root keeps Furo's own working search and loads no chrome.
  • Move the docs toolchain to gp-sphinx 0.1.0a38, taking upstream's fix for .md twin links on genindex, py-modindex, and search — pages that have no twin.

The shell integration is only correct where the build is nested

This tree is served from two shapes, and they disagree:

Consumer Serves at /_shell/shell.js /search/
libtmux.org assembler, and a local preview of it /py/<version>/api/ the shell's the shell's Pagefind search
docs.yml → S3 bucket root / nothing this build's own search page

Root-relative paths are right for the first and wrong for the second. Unguarded, merging this would have pointed libtmux.git-pull.com/search/ at itself — a page that meta-refreshes to its own URL for ever — and asked every page for a shell.js that 404s.

So the integration is on by default, for the two consumers that nest it, and docs.yml sets LIBTMUX_DOCS_STANDALONE=1 to opt out. Belt and braces: the stub redirects only when its own path is not already the target, so a tree served at a root cannot loop even if the gate is ever wrong.

The token adapter stays on in both. It degrades to stock Furo by itself, which is what its fallbacks are for.

Changes

docs/conf.py: html_css_files gains libtmux-org.css, after css/custom.css so its overrides win the cascade at equal specificity. html_js_files and templates_path are computed from the gate above; both spell out the value gp_sphinx would otherwise supply, so a change to its default cannot silently drop either.

docs/_static/libtmux-org.css: @imports the shared tokens.css and translates --lt-* onto Furo's --color-* for light, data-theme="dark", and prefers-color-scheme: dark.

docs/_templates_shell/search.html: replaces the theme's search page outright — no {% extends %}. Its own directory, so the gate drops it without disturbing the templates gp_sphinx expects. The wording matches the rediraffe stubs already in this tree so the site audit's redirect check skips it instead of flagging an empty page.

pyproject.toml: gp-sphinx and siblings move to 0.1.0a38. sphinx-gp-llms resolves from git-pull/gp-sphinx@3b0bdc15 over HTTPS — a public commit that clones anonymously — until a release carries its md-twin fix. That commit reports 0.1.0a38, the version pinned alongside it, so no dependency override is needed. Deleting the [tool.uv.sources] block is all it will take.

Design decisions

Import the tokens, never copy them. The values stay live at the CDN, so a chrome-color fix reaches an already-published build without a rebuild here. Only the mapping is fixed at build time.

Every var(--lt-*) carries Furo's own stock value as its fallback. This is what makes the file repetitive, and it is load-bearing: a var() naming an undefined custom property with no fallback resolves to the guaranteed-invalid value, so --color-background-primary would compute to unset rather than white. Any page whose cross-origin tokens.css fetch fails would then render worse than the unskinned page this file closes. The fallbacks are Furo's own colors rather than libtmux's, so a failed fetch degrades to plain Furo instead of vendoring the palette.

Redirect from a guard, not a bare <meta refresh>. A refresh fires wherever the page is served. The guard compares the page's own path to the target, which is the only form that is correct under both layouts above.

Test plan

Each build below is the other's negative control: the same assertions flip between the two modes.

  • uv sync --all-extras --dev resolves with no credentials — proven with SSH disabled: GIT_SSH_COMMAND=/bin/false git ls-remote https://github.com/git-pull/gp-sphinx.git
  • just build-docs succeeds in both modes
  • Shell mode: pages load /_shell/shell.js, and libtmux-org.css after css/custom.css
  • Shell mode: search/index.html is the guarded redirect
  • Standalone (LIBTMUX_DOCS_STANDALONE=1): no shell.js, and search/index.html is Furo's own search page
  • libtmux-org.css loads in both modes
  • index.html links its .md twin, and genindex, py-modindex, search link none — the positive control separates "0.1.0a38's fix works" from "twins are off"
  • uv run ruff check ., uv run ruff format ., uv run mypy src tests, uv run pytest --reruns 0
  • With tokens.css unreachable, pages render as stock Furo in light and dark

tony added 6 commits September 5, 2026 03:42
Furo's own search.html needs a JS index this build doesn't serve at
this path; the shell already indexes every port at /search/. Overriding
the search.html template (rather than adding a page) works regardless
of the theme, and the redirect wording matches the existing rediraffe
stubs so scripts/audit-site.mjs's redirect check skips it.
Closes notes/status.md's "Python and C++ are unskinned islands" glitch:
without this file Furo has no --lt-* mapping and paints its own stock
blue. Imports https://libtmux.org/_shell/tokens.css and maps the shared
~25 semantic tokens onto Furo's --color-* contract. The html_css_files
and html_js_files entries wiring it (plus shell.js) into conf.py landed
in 7380cd478 alongside an unrelated search-page fix from concurrent work
in this worktree.
…hable

A var() on an undefined custom property with no fallback resolves to the
guaranteed-invalid value, so every remapped --color-* would compute to
unset until libtmux.org resolves (notes/status.md: never deployed) --
worse than the stock-Furo glitch this adapter exists to close. Fall back
to Furo's own stock color per property instead, so an unreachable
tokens.css degrades to unmodified Furo rather than a broken page.
Pagefind logs a missing html[lang] warning when indexing the assembled
site; the rediraffe-generated stubs in this tree have the same gap, but
there's no reason to match it here too.
An absolute https://libtmux.org/_shell/ URL resolves nowhere until the site
is deployed, so the injected chrome was invisible in every local preview and
the design-token bridge could not be checked at all. A root-relative path
resolves on both the deployed origin and a local preview server.
why: The previous pin resolved sphinx-gp-llms from a private fork over
SSH. No runner and no outside contributor holds a key for it, so
`uv sync --all-extras --dev` — the install step in both tests.yml and
docs.yml — failed with `Permission denied (publickey)` before a test
ran. The fix it reached for has since landed on public upstream main.

what:
- Bump gp-sphinx and its siblings 0.1.0a37 -> 0.1.0a38, all on PyPI
- Point sphinx-gp-llms at git-pull/gp-sphinx@3b0bdc15 over HTTPS, a
  public commit that clones anonymously
- Drop `[tool.uv] override-dependencies`: that commit reports 0.1.0a38,
  matching the pin above, so nothing needs overriding
@codecov

codecov Bot commented Sep 6, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.37%. Comparing base (a7ff6b6) to head (1aae8a6).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master     #755      +/-   ##
==========================================
- Coverage   52.45%   52.37%   -0.09%     
==========================================
  Files          26       26              
  Lines        3729     3729              
  Branches      747      747              
==========================================
- Hits         1956     1953       -3     
- Misses       1469     1472       +3     
  Partials      304      304              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

tony added 2 commits September 6, 2026 05:18
why: The header cited a checkout path under the author's home
directory as the source of the fallback colours — a tracked file in a
public repository naming a machine only one person has. The rest had
grown past what a reader of this file needs.

what:
- Name the gp-furo-tokens package instead of a local checkout path
- Say which repository the design notes live in, rather than citing
  paths that resolve nowhere from here
- Trim to what the file cannot be read without: the mapping's purpose,
  why every fallback is Furo's own value, and the cascade order
why: The shell integration is correct only where this tree is served
under libtmux.org, at /py/<version>/api/. docs.yml publishes the same
tree to the bucket root behind libtmux.git-pull.com, where /_shell/
holds nothing and /search/ is the page itself — so the override turned
that host's working search into a page that refreshed to itself for
ever, and asked for a shell.js that 404s.

what:
- Gate the search override and shell.js on LIBTMUX_DOCS_STANDALONE,
  on by default for the two consumers that nest the build, and set to
  1 by docs.yml, which does not
- Move the override to _templates_shell so the gate can drop it
  without disturbing the templates gp_sphinx already expects
- Guard the redirect on the page's own path, so a tree served at a
  root cannot refresh to itself even with the gate wrong
- Leave the token adapter on in both: it degrades to stock Furo alone
@tony
tony marked this pull request as ready for review September 6, 2026 10:21
tony added 3 commits September 6, 2026 09:48
why: Which of chrome and the search override a build carries decides
whether libtmux.git-pull.com keeps a working search or serves a page
that redirects to itself. Nothing re-ran that check; it was a pair of
builds done by hand, and docs.yml only runs on master, so a wrong gate
would first be seen on the deployed site.

what:
- Read docs/conf.py the way Sphinx does, under both env settings, and
  assert what each resolves templates_path and html_js_files to
- Assert the override sits outside _templates, which the gate cannot
  drop, and that the redirect is guarded on the page's own path
- Both bite: flipping the gate fails four, replacing the guard with a
  bare meta refresh fails the fifth
why: The flag is correct only while this tree is published to a bucket
root. When the sync moves to a per-port prefix under libtmux.org the
build becomes nested and the flag becomes wrong, but nothing said so —
and the failure is quiet: the port publishes with no chrome and the
wrong search, which reads as a broken shell rather than a stale flag.

what:
- Name the condition that retires the flag, and what leaving it does
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant